package com.gitee.huanminabc.fastboot.web.validation;



import com.gitee.huanminabc.jcommon.reflect.AnnotationUtil;
import com.gitee.huanminabc.jcommon.reflect.ReflectPath;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: huanmin
 * @create: 2025-04-02 15:04
 **/
public class ValidationUtil {
    public static final List<Class<?>> validationAnnotations = new ArrayList<>();
    public static final Map<Class<?>, ValidationVerify> verifyMap = new HashMap<>();

    static {
        registerValidationAnnotation(new DepthValidationVerify());
        registerValidationAnnotation(new MaxValidationVerify());
        registerValidationAnnotation(new MinValidationVerify());
        registerValidationAnnotation(new NotBlankValidationVerify());
        registerValidationAnnotation(new NotEmptyValidationVerify());
        registerValidationAnnotation(new NotNullValidationVerify());
        registerValidationAnnotation(new GroupValidationVerify());
        validationAnnotations.addAll(verifyMap.values().stream().map(ValidationVerify::getAnnotation).collect(Collectors.toList()));
    }

    //注册验证注解
    public static void registerValidationAnnotation(ValidationVerify validationVerify) {
        verifyMap.put(validationVerify.getAnnotation(), validationVerify);
    }


    //校验方法参数
    public static void verifyMethod(Method method, Object[] args) throws Exception {
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            //获取参数上的注解
            Annotation[] annotations = parameter.getAnnotations();
            for (Annotation annotation : annotations) {
                //如果是验证注解
                if (validationAnnotations.contains(annotation.annotationType())) {
                    //获取参数值
                    Object arg = args[i];
                    //校验参数值
                    verifyParameter(arg, annotation, ReflectPath.getMethodParam(method, parameter));
                }
            }
        }
    }

    public static void verifyClassGroup(Object args, Class<?>[] groupClass, String gprmc) throws Exception {
        Class<?> aClass = args.getClass();
        //如果是数组
        if (aClass.isArray()) {
            //获取数组元素类型
            Class<?> componentType = aClass.getComponentType();
            //如果是基本类型,那么直接返回
            if (componentType.isPrimitive()) {
                return;
            }
            //如果是对象数组,那么遍历数组元素
            Object[] array = (Object[]) args;
            for (int i = 0; i < array.length; i++) {
                Object element = array[i];
                verifyClassGroup(element, groupClass, gprmc + "[" + i + "]");
            }
            return;
        }
        //如果是Collection类型
        if (Collection.class.isAssignableFrom(aClass)) {
            Collection<?> collection = (Collection<?>) args;
            int index = 0;
            for (Object element : collection) {
                verifyClassGroup(element, groupClass, gprmc + "[" + index + "]");
                index++;
            }
            return;
        }
        //如果是Map类型,只校验value
        if (Map.class.isAssignableFrom(aClass)) {
            Map<?, ?> map = (Map<?, ?>) args;
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                Object key = entry.getKey();
                Object value = entry.getValue();
                verifyClassGroup(value, groupClass, gprmc + "[" + key + "]");
            }
            return;
        }

        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            List<Annotation> fieldAnnotations = AnnotationUtil.getFieldAnnotations(declaredField, validationAnnotations.toArray(new Class[0]));
            //如果有验证注解
            if (!fieldAnnotations.isEmpty()) {
                //获取字段值
                Object fieldValue = declaredField.get(args);
                for (Annotation fieldAnnotation : fieldAnnotations) {
                    //如果groupClass不是空,那么值校验组中存在的
                    if (groupClass != null && groupClass.length > 0) {
                        //获取验证组
                        Class<?>[] groups = AnnotationUtil.getAnnotationPropertyValueT(fieldAnnotation, "groups", Class[].class);
                        //如果验证组不包含当前组,那么跳过
                        if (groups != null && !new HashSet<>(Arrays.asList(groups)).containsAll(Arrays.asList(groupClass))) {
                            continue;
                        }
                    }
                    String newGprmc;
                    if (gprmc != null) {
                        newGprmc = gprmc + "->" + ReflectPath.getField( declaredField);
                    } else {
                        newGprmc =  ReflectPath.getField( declaredField);
                    }
                    verifyParameter(fieldValue, fieldAnnotation, newGprmc);
                }
            }
        }

    }

    //校验对象内部的成员
    public static void verifyClass(Object args) throws Exception {
        verifyClass(args, null);
    }

    public static void verifyClass(Object args, String gprmc) throws Exception {
        verifyClassGroup(args, null, gprmc);
    }

    private static void verifyParameter(Object arg, Annotation annotation, String gprmc) throws Exception {
        //获取验证器
        ValidationVerify validationVerify = verifyMap.get(annotation.annotationType());
        if (validationVerify != null) {
            //校验参数值
            validationVerify.verify(arg, annotation, gprmc);
        }
    }

}
